package com.ssd.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.dkd.common.core.domain.entity.SysRole;
import com.dkd.common.core.domain.entity.SysUser;
import com.dkd.common.core.domain.model.LoginUser;
import com.ssd.api.couponAndIntegral.PointsRecordTotalApi;
import com.ssd.entity.CommonUser;
import com.ssd.entity.vo.CommonUserVo;
import com.ssd.exception.LogicException;
import com.ssd.mapper.CommonUserMapper;
import com.ssd.service.ICommonUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ssd.tencent.WechatService;
import com.ssd.utils.IdUtils;
import com.ssd.utils.UserContext;
import com.ssd.view.BaseResponse;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * c端用户表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-11-14
 */
@Service
public class CommonUserServiceImpl extends ServiceImpl<CommonUserMapper, CommonUser> implements ICommonUserService {
    @Resource
    private WechatService wechatService;
    @Resource
    private PointsRecordTotalApi pointsRecordTotalApi;
    @Resource
    private RedisTemplate redisTemplate;

    private int expireTime=300;

    protected static final long MILLIS_SECOND = 1000;

    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

    @Override
    public BaseResponse loginForCommonUser(String code) throws IOException {
        // code换openId
        String openIdResDTO = wechatService.getOpenid(code);
        if (ObjectUtil.isEmpty(openIdResDTO) ) {
            // openid申请失败
            throw new LogicException("openid申请失败");
        }
        CommonUser commonUser = lambdaQuery().eq(CommonUser::getOpenId, openIdResDTO).one();
        //如果未从数据库查到，需要新增数据
        if (ObjectUtil.isEmpty(commonUser)) {
            commonUser = new CommonUser();
            Long snowflakeNextId = IdUtil.getSnowflake().nextId();
            //把long转为int
            commonUser.setId(snowflakeNextId);//id
            commonUser.setOpenId(openIdResDTO);//openid
            commonUser.setNickname("普通用户" + RandomUtil.randomInt(10000, 99999));//昵称
            commonUser.setAvatar("");//头像
            save(commonUser);
            //远程调用生成总积分记录表
            pointsRecordTotalApi.createUserPointsRecordTotal(snowflakeNextId);
        }
        LoginUser user = new LoginUser();
        user.setUserId(commonUser.getId());
        SysUser sysUser = new SysUser();
        ArrayList<SysRole> list = new ArrayList<>();
        SysRole sysRole = new SysRole();
        sysRole.setRoleId(2L);
        list.add(sysRole);
        sysUser.setRoles(list);
        sysUser.setUserName(commonUser.getNickname());
        sysUser.setPhonenumber(commonUser.getPhone());
        user.setUser(sysUser);
        
        refreshToken(user);//刷新令牌有效期

        //创建视图对象
        CommonUserVo commonUserVo = BeanUtil.copyProperties(commonUser, CommonUserVo.class);
        commonUserVo.setToken(createToken(user));//设置token

        return new BaseResponse(commonUserVo);
    }
    /**
     * 刷新令牌有效期
     *
     * @param loginUser 登录信息
     */
    public void refreshToken(LoginUser loginUser)
    {
        // 更新登录时间
        loginUser.setLoginTime(System.currentTimeMillis());
        // 根据新的登录时间，重新计算令牌有效期
        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
        // 生成loginUser缓存键
        String userKey = getTokenKey(loginUser.getToken());
        // 使用新的有效期重新缓存用户对象
        redisTemplate.opsForValue().set(userKey, loginUser, expireTime, TimeUnit.MINUTES);
    }
    private String getTokenKey(String uuid)
    {
        return "login_tokens:" + uuid;
    }
    /**
     * 创建令牌
     *
     * @param loginUser 用户信息
     * @return 令牌
     */
    public String createToken(LoginUser loginUser)
    {
        // 生成一个快速UUID作为用户令牌
        String token = IdUtils.fastUUID();
        // 将生成的令牌设置给用户登录对象
        loginUser.setToken(token);

        // 刷新redis中用户令牌
//        refreshToken(loginUser);
        // 创建一个存储令牌相关数据的Map
        Map<String, Object> claims = new HashMap<>();
        // 将用户令牌存入claims中
        claims.put("login_user_key", token);
        // 使用claims创建用户登录令牌
        return createToken(claims);
    }

    /**
     * 从数据声明生成令牌
     *
     * @param claims 数据声明
     * @return 令牌
     */
    private String createToken(Map<String, Object> claims)
    {
        String token = Jwts.builder()
                .setClaims(claims)
                // 使用HS512算法和secret密钥对JWT进行签名
                .signWith(SignatureAlgorithm.HS512, "abcdefghijklmnopqrstuvwxyz").compact();
        return token;
    }
    @Override
    public BaseResponse updatePhone(String phoneCode) {
        // 通过微信手机号授权码获取用户电话信息
        String phone = wechatService.getPhone(phoneCode);

        // 创建一个CommonUser对象，用于更新用户信息
        CommonUser commonUser = new CommonUser();
        // 设置当前用户ID
        commonUser.setId(UserContext.currentUserId());
        // 设置用户新电话
        commonUser.setPhone(phone);
        // 更新数据库中的用户电话信息
        updateById(commonUser);

        return new BaseResponse(true);
    }
}
